/*******************************************************************************
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *  
 * Copyright (c) 2011 Michael Chan.
 ******************************************************************************/
package com.google.code.solrdimension.solrqueryutil;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.google.code.solrdimension.config.StaticConfiguration;

/**
 * Utilitiy class for various actions to translate data from solr
 * 
 * @author mhc
 * 
 */
public class QueryUtil {

    private static Pattern MATCH_SOLR_FACET_PREFIX_HEADER_PATTERN = Pattern.compile(StaticConfiguration.SORL_FACET_PREFIX_REGEX);

    private static Logger logger = LoggerFactory.getLogger(QueryUtil.class);

    /**
     * This method extracts the dimension id (field name) and dimension value id
     * (field value) from the solrFilterQuery and put the two in an array
     * 
     * The first value is DimensionID and the second value is DimensionValueId
     * 
     * @param solrFilterQuery
     * @return
     */
    public static String[] extractDimensionIdAndValueId(String solrFilterQuery) {

        String[] result = null;

        String dimensionIDprefix = null;

        if (solrFilterQuery.startsWith(StaticConfiguration.FIELD_PREFIX)) {
            dimensionIDprefix = StaticConfiguration.FIELD_PREFIX;
        } else if (solrFilterQuery.startsWith(StaticConfiguration.MULTI_VALUED_FIELD_PREFIX)) {
            dimensionIDprefix = StaticConfiguration.MULTI_VALUED_FIELD_PREFIX;
        }

        if (dimensionIDprefix != null) {

            String[] solrFilterQueryArray = extractFieldAndValue(solrFilterQuery);

            String dimensionId = StringUtils.replace(solrFilterQueryArray[0], dimensionIDprefix, "");
            String dimensionValueId = solrFilterQueryArray[1];

            result = new String[] { dimensionId, dimensionValueId };

        }

        return result;
    }

    /**
     * Take a solrFilterQuery and extract the field and value by doing
     * String.split
     * 
     * @param solrFilterQuery
     * @return An Array of splitted string
     */
    public static String[] extractFieldAndValue(String solrFilterQuery) {

        String[] result = null;

        String[] solrFilterQueryArray = solrFilterQuery.split(StaticConfiguration.SOLR_FACET_FACETVALUE_SEPARATOR);

        if (solrFilterQueryArray.length == 2) {

            String field = solrFilterQueryArray[0];
            String value = solrFilterQueryArray[1];

            result = new String[] { field, value };
        }

        return result;
    }

    public static boolean isDimensionIdInFilter(String dimensionId, List<String> appliedFilters) {

        boolean result = false;
        if (appliedFilters != null && !appliedFilters.isEmpty()) {
            for (String filter : appliedFilters) {

                String[] dimensionIdAndValueId = extractDimensionIdAndValueId(filter);

                if (dimensionIdAndValueId != null && dimensionIdAndValueId.length == 2) {

                    if (dimensionIdAndValueId[0].equals(dimensionId)) {
                        return true;
                    }

                }

            }
        }
        return result;
    }

    /**
     * Process the {@link QueryResponse}, extract all fields containing the
     * pattern f.[field name].facet.prefix, If there is a match, add the result
     * to a Map in the following format: prefix value, field name
     * 
     * 
     * @param response
     *            {@link QueryResponse}
     * @return a {@link SimpleOrderedMap} containing prefix field name, field
     *         prefixes
     */
    public static SimpleOrderedMap<String> getFacetPrefixFromQueryResponse(QueryResponse response) {

        SimpleOrderedMap<String> results = null;

        SimpleOrderedMap<String> params = (SimpleOrderedMap<String>) response.getHeader().get(StaticConfiguration.SOLR_RESPONSE_PARAMS);

        Iterator<Map.Entry<String, String>> it = params.iterator();

        logger.debug("Matching prefixes...");

        while (it.hasNext()) {

            Map.Entry entry = it.next();

            if (entry.getValue() instanceof String) {

                logger.debug("Entry:" + entry.getKey() + " Value: " + entry.getValue());

                Matcher matcher = MATCH_SOLR_FACET_PREFIX_HEADER_PATTERN.matcher(entry.getKey().toString());

                if (matcher.find()) {

                    logger.debug("A Match is found for facet prefix");
                    if (results == null) {
                        results = new SimpleOrderedMap<String>();

                    }

                    String fieldName = matcher.group(1);
                    // check if the map already got the key
                    if (results.get(fieldName) != null) {

                        logger.warn("A field with the name: " + fieldName + " is already in the Map... adding it anyway");

                    }
                    results.add(fieldName, entry.getValue().toString());

                }

            }

        }
        return results;
    }

}
